package maa.action.client;

import maa.action.Action;
import maa.action.ActionException;
import maa.action.ActionResult;
import maa.dao.h2.UserDAOimpl;
import maa.dao.DAOCommand;
import maa.dao.DAOException;
import maa.dao.DAOManager;
import maa.database.ConnectionPool;
import maa.entity.Gender;
import maa.entity.User;
import maa.util.FieldValidator;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Date;
import java.util.UUID;

public class EditProfile implements Action {
    @Override
    public ActionResult execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        ActionResult actionResult = new ActionResult();
        HttpSession session = req.getSession();
        User currentUser = (User) session.getAttribute("user");
        final User user = new User();
        String realPassword = currentUser.getPassword();
        String curPassword = req.getParameter("current-password");
        String newPassword = req.getParameter("new-password");
        String confirmNewPassword = req.getParameter("confirm-new-password");
        String email = req.getParameter("email");
        String name = req.getParameter("name");
        String surname = req.getParameter("surname");
        String gender = req.getParameter("gender").toUpperCase();
        String birthdate = req.getParameter("birthdate");
        if (!FieldValidator.isValidEmail(email)) {
            req.setAttribute("incorrect_email", "Email should be different");
            actionResult.setResult("user-self-update");

            return actionResult;
        }
        if (!FieldValidator.isValidName(name)) {
            req.setAttribute("incorrect_name", "Name should start with a capitol letter, consist of only letters and can be 1 to 30 symbols");
            actionResult.setResult("user-self-update");
            return actionResult;
        }
        if (!FieldValidator.isValidSurname(surname)) {
            req.setAttribute("incorrect_gender", "Surname should start with a capitol letter, consist of only letters and can be 1 to 40 symbols");
            actionResult.setResult("user-self-update");
            return actionResult;
        }
        if (!FieldValidator.isValidGender(gender)) {
            req.setAttribute("incorrect_surname", "Gender should be either 'MALE' or 'FEMALE'");
            actionResult.setResult("user-self-update");
            return actionResult;
        }
        if (!FieldValidator.isValidBirthdate(birthdate)) {
            req.setAttribute("incorrect_birthdate", "Birthdate should be submitted in the following format: yyyy-mm-dd");
            actionResult.setResult("user-self-update");
            return actionResult;
        }
        if (!FieldValidator.isValidPassword(curPassword)) {
            req.setAttribute("invalid_password", "Wrong password.");
            actionResult.setResult("user-self-update");
            return actionResult;
        }
        String currentPassword = encryptPassword(req.getParameter("current-password"));
        if (!currentPassword.equals(realPassword)) {
            req.setAttribute("incorrect_password", "Invalid current password.");
            actionResult.setResult("user-self-update");
            return actionResult;
        }
        String currPass = encryptPassword(currentPassword);
        user.setPassword(currPass);
        if (!newPassword.isEmpty() || !confirmNewPassword.isEmpty()) {
            if (!FieldValidator.isValidPassword(newPassword)) {
                req.setAttribute("invalid_new_password", "Invalid new password");
                actionResult.setResult("user-self-update");
                return actionResult;
            }
            if (!newPassword.equals(confirmNewPassword)) {
                req.setAttribute("unmatching_passwords", "New password and confirmed new password should match. Please try again!");
                actionResult.setResult("user-self-update");
                return actionResult;
            }
            String newPass = encryptPassword(newPassword);
            user.setPassword(newPass);
        }
        user.setUuid(UUID.fromString(req.getParameter("uuid").substring(0, req.getParameter("uuid").length() - 1)));
        user.setName(name);
        user.setEmail(email);
        user.setSurname(surname);
        user.setBirthdate(Date.valueOf(birthdate));
        user.setGender(Gender.valueOf(gender));
        final String p = user.getPassword();
        final String e = user.getEmail();
        ConnectionPool connectionPool = ConnectionPool.getInstance();
        DAOManager daoManager = new DAOManager(connectionPool.getConnection());
        DAOCommand daoCommand = new DAOCommand() {
            @Override
            public Object execute(DAOManager daoManager) throws ActionException {
                UserDAOimpl userDAO = daoManager.getUserDAO();
                try {
                    return userDAO.update(user);
                } catch (DAOException e) {
                    throw new ActionException("Exception in userDAO.update(user)");
                }
            }
        };
        Boolean flag = (Boolean) daoManager.executeAndClose(daoCommand);

        if (flag) {
            daoManager.setConnection(connectionPool.getConnection());
            DAOCommand command = new DAOCommand() {
                @Override
                public Object execute(DAOManager daoManager) throws ActionException {
                    UserDAOimpl userDAO = daoManager.getUserDAO();
                    User user = null;
                    try {
                        user = userDAO.findByEmailAndPassword(e, p);
                    } catch (DAOException e) {
                        throw new ActionException("Exception in userDAO.findByEmailAndPassword(email, password)");
                    }
                    return user;
                }
            };
            User editedUser = (User) daoManager.executeAndClose(command);
            session.setAttribute("user", editedUser);
            actionResult.setResult("success");
            actionResult.setRedirected(true);
        }
        return actionResult;
    }

    private static String encryptPassword(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        MessageDigest crypt = MessageDigest.getInstance("SHA-1");
        crypt.reset();
        crypt.update(password.getBytes("UTF-8"));
        return new BigInteger(1, crypt.digest()).toString(16);
    }
}
